package com.shell.customer.accreditation.service.impl;

import java.io.File;
import java.io.IOException;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;

import org.dom4j.DocumentException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import com.shell.bee.base.exception.UnCheckMsgException;
import com.shell.bee.base.utils.DateUtil;
import com.shell.bee.base.utils.JsonUtil;
import com.shell.bee.base.utils.RandomUtil;
import com.shell.bee.base.utils.SpringContextUtil;
import com.shell.bee.base.utils.StringUtil;
import com.shell.bee.base.utils.SystemUtil;
import com.shell.bee.cfca.CfcaConfiguration;
import com.shell.bee.cfca.base.po.CfcaSmsLog;
import com.shell.bee.cfca.base.service.CfcaSmsLogService;
import com.shell.bee.contract.ContConfiguration;
import com.shell.bee.contract.ContTemplateHelper;
import com.shell.bee.entity.mvc.RetMsg;
import com.shell.bee.esign.po.EsAcctAuth;
import com.shell.bee.esign.service.EsignSignService;
import com.shell.bee.esign.vo.EsignAuthResponse;
import com.shell.bee.file.po.PubFile;
import com.shell.bee.file.service.PubFileUploadService;
import com.shell.bee.report.utils.PdfUtils;
import com.shell.constant.rel.CustomerConstants;
import com.shell.customer.accreditation.AccreditEvent;
import com.shell.customer.accreditation.keyword.AuthorizationKeyword;
import com.shell.customer.accreditation.rx.BroadcastAfterAccreditSubscriber;
import com.shell.customer.accreditation.rx.ContApplySubscriber;
import com.shell.customer.accreditation.rx.ContSignSubscriber;
import com.shell.customer.accreditation.rx.EsignOpenAcctSubscriber;
import com.shell.customer.accreditation.rx.OpenCusAcctForAccreditPassSubscriber;
import com.shell.customer.accreditation.rx.SaveUsersSubscriber;
import com.shell.customer.accreditation.rx.SendMsgForTbCusSubscriber;
import com.shell.customer.accreditation.rx.SetCreditLineSubscriber;
import com.shell.customer.accreditation.rx.SetCusLvlSubscriber;
import com.shell.customer.accreditation.rx.SetCusOptSubscriber;
import com.shell.customer.accreditation.rx.SetCusRelAndTagAfterAccreditSubscriber;
import com.shell.customer.accreditation.rx.SetFilesSubscriber;
import com.shell.customer.accreditation.rx.SetGroupSubscriber;
import com.shell.customer.accreditation.rx.SetInviterSubscriber;
import com.shell.customer.accreditation.rx.UpdateCuAcctSubscriber;
import com.shell.customer.accreditation.rx.UpdateCusSubscriber;
import com.shell.customer.accreditation.rx.UpdateUserAndOrganSubscriber;
import com.shell.customer.accreditation.service.AccreditationService;
import com.shell.customer.accreditation.vo.AccreditationVo;
import com.shell.customer.accreditation.vo.CusOptVo;
import com.shell.customer.accreditation.vo.UserVo;
import com.shell.customer.base.MsgEvent;
import com.shell.customer.base.dao.AccreditationDao;
import com.shell.customer.base.rx.SendMsgSubscriber;
import com.shell.customer.base.service.CusAcctService;
import com.shell.customer.base.service.CusAcctUseService;
import com.shell.customer.base.service.CusExtraService;
import com.shell.customer.base.service.CusOptService;
import com.shell.customer.base.service.CusRecService;
import com.shell.customer.base.vo.Message;
import com.shell.customer.cfca.service.CfcaAuthTxService;
import com.shell.customer.esign.service.EsignAuthTxService;
import com.shell.customer.group.service.CusGrpService;
import com.shell.customer.invitation.service.InvtCusService;
import com.shell.customer.po.CusAcct;
import com.shell.customer.po.CusExtra;
import com.shell.customer.po.CusInvt;
import com.shell.customer.po.CusOpt;
import com.shell.customer.po.CusRec;
import com.shell.customer.util.CustomerUtil;
import com.shell.feign.PubMessageFeign;
import com.shell.feign.PubProtocolFeign;
import com.shell.feign.PubUserExtraFeign;
import com.shell.framework.utils.CommonDataUtil;
import com.shell.framework.utils.SysDateUtil;
import com.shell.governor.modules.message.keyword.PaperlessSignKeyWord;
import com.shell.governor.modules.message.keyword.SmsAutPassKeyword;
import com.shell.governor.modules.message.keyword.SmsAutPwdKeyword;
import com.shell.governor.modules.message.keyword.SmsAutRejectKeyword;
import com.shell.governor.modules.message.keyword.SmsAuthApplyKeyword;
import com.shell.governor.modules.message.keyword.SysAutFirstTrialKeyword;
import com.shell.governor.modules.message.keyword.SysAutLastTrialKeyword;
import com.shell.governor.modules.message.keyword.SysAutRejectKeyword;
import com.shell.governor.modules.po.PubProtocol;
import com.shell.governor.user.po.PubUser;
import com.shell.governor.user.vo.PubUserVo;
import com.shell.sms.SMSResponse;
import com.timevale.esign.sdk.tech.bean.result.Result;

import freemarker.template.TemplateException;
import rx.Observable;

@Service("accreditationService")
public class AccreditationServiceImpl implements AccreditationService {
	private Logger logger = LoggerFactory.getLogger(getClass());
	@Autowired
	private AccreditationDao accreditationDao;
	@Resource(name = "${file.updownload.service}")
	private PubFileUploadService pubFileUploadService;
	@Autowired
	private CusAcctService pubCusAcctService;
	@Autowired
	private CusAcctUseService cusAcctUseService;
	@Autowired
	private CusOptService pubCusOptService;
	@Autowired
	private CusRecService customerCService;
	@Autowired
	private CusExtraService pubCusExtraService;
	@Autowired
	private PubUserExtraFeign userExtraFeign;
	@Autowired
	private SaveUsersSubscriber saveUsersSubscriber;
	@Autowired
	private SetGroupSubscriber setGroupSubscriber;
	@Autowired
	private SetCusOptSubscriber setCusOptSubscriber;
	@Autowired
	private SetFilesSubscriber setFilesSubscriber;
	@Autowired
	private UpdateCuAcctSubscriber updateCuAcctSubscriber;
	@Autowired
	private UpdateCusSubscriber updateCusSubscriber;
	@Autowired
	private SetCusLvlSubscriber setCusLvlSubscriber;
	@Autowired
	private SetInviterSubscriber setInviterSubscriber;
	@Autowired
	private SendMsgSubscriber sendMsgSubscriber;
	@Autowired
	private UpdateUserAndOrganSubscriber updateUserAndOrganSubscriber;
	@Autowired
	private SetCusRelAndTagAfterAccreditSubscriber setCusRelAndTagAfterAccreditSubscriber;
	@Autowired
	private OpenCusAcctForAccreditPassSubscriber cusAcctForPassSubscriber;
	@Autowired
	private SetCreditLineSubscriber setCreditLineSubscriber;
	@Autowired
	private BroadcastAfterAccreditSubscriber broadcastAfterAccreditSubscriber;
	@Autowired
	private EsignOpenAcctSubscriber esignOpenAcctSubscriber;
	@Autowired
	private ContApplySubscriber contApplySubscriber;
	@Autowired
	private ContSignSubscriber contSignSubscriber;
	@Autowired
	private InvtCusService invtCusService;
	@Autowired
	private EsignAuthTxService esignAuthTxService;
	@Autowired
	private CusGrpService cusGrpService;
	@Autowired
	private EsignSignService esignSignService;
	@Autowired
	private PubProtocolFeign pubProtocolFeign;
	@Autowired
	private PubMessageFeign pubMessageFeign;
	@Value("${sms.gateway: ''}")
	private String smsGateway;
	@Autowired
	private CfcaSmsLogService cfcaSmsLogService;
	@Autowired
	private CfcaAuthTxService cfcaAuthTxService;
	@Autowired
	private SendMsgForTbCusSubscriber sendMsgForTbCusSubscriber;
	private static Map<String, String> templateMap = new HashMap();
	static {
		try {
			Map<String, String> conTempNameMap;
			Map<String, Map<String, String>> constantMap = SystemUtil
					.getConstantsCnNameValueMap(CustomerConstants.class);
			conTempNameMap = (Map) constantMap.get("ConTemplateName");
			for (String key : conTempNameMap.keySet()) {
				templateMap.put(conTempNameMap.get(key), key);
			}
		} catch (Exception e) {
			
			e.printStackTrace();
		}
	}

	private static final String ACCREDITATION_TEMPLATE_PATH = AccreditationServiceImpl.class
			.getResource("/template/accreditation/").getPath();

	public AccreditationVo getCustomerInfo(String cusId) {
		AccreditationVo vo = this.accreditationDao.getCustomerInfo(cusId);

		List<CusInvt> invts = this.invtCusService.getCusInvtByCusName(vo.getCustomerC().getCusName());
		vo.setNeedInviteCode((invts == null) || (invts.size() == 0));

		CusExtra cusExtra = (CusExtra) this.pubCusExtraService.selectByKey(vo.getCustomerC().getCusId());
		if (cusExtra != null) {
			if (StringUtil.notEmpty(cusExtra.getInviterId())) {
				String inviteCode = this.userExtraFeign.getInviteCode(cusExtra.getInviterId(),
						cusExtra.getInviterCusId());
				vo.setInviteCode(inviteCode);
			}
			vo.setCreditLine(cusExtra.getCreditLine());
		}
		return vo;
	}

	public Map<String, Object> getCusTypeByInviteCode(String inviteCode) {
		return null;
	}

	public void saveAccreditationData(AccreditationVo accreditationVo) {
		CusRec cusRec = accreditationVo.getCustomerC();
		CusOpt cusOpt = new CusOpt();
		boolean waitPayAuth = false;
		if ((CustomerUtil.onEsign()) && (!"PERSONAL".equals(cusRec.getCusType()))
				&& (!"5".equals(cusRec.getCusState()))) {
			waitPayAuth = true;
		}
		if (waitPayAuth) {
			cusOpt.setCusState("6");
			cusOpt.setNextState("2");
		} else {
			cusOpt.setCusState("2");
			cusOpt.setNextState("3");
		}
		cusOpt.setBizCode("0");
		cusOpt.setCurState(accreditationVo.getCustomerC().getCusState());

		AccreditEvent accreditEvent = new AccreditEvent();
		accreditEvent.setAccreditationVo(accreditationVo);
		accreditEvent.setCusOpt(cusOpt);

		Observable<AccreditEvent> observers = Observable.just(accreditEvent);
		observers.subscribe(this.contApplySubscriber);
		observers.subscribe(this.contSignSubscriber);
		observers.subscribe(this.setFilesSubscriber);
		observers.subscribe(this.updateCuAcctSubscriber);
		observers.subscribe(this.setCusOptSubscriber);
		observers.subscribe(this.updateCusSubscriber);
		observers.subscribe(this.setInviterSubscriber);
		observers.subscribe(this.setGroupSubscriber);
		observers.subscribe(this.saveUsersSubscriber);
		if (!waitPayAuth) {
			sendSaveAccreditationMsg(accreditEvent);
		}
	}

	private void sendSaveAccreditationMsg(AccreditEvent accreditEvent) {
		AccreditationVo accreditationVo = accreditEvent.getAccreditationVo();

		List<Message> messages = new ArrayList();

		String approverEntId = this.cusGrpService.findGroupEnt(accreditationVo.getCustomerC().getGrpId(),
				"GROUP_FIRST_TRIAL");

		SysAutFirstTrialKeyword keyWord = new SysAutFirstTrialKeyword();
		keyWord.setCusName(accreditationVo.getCustomerC().getCusName());
		keyWord.setApplyDate(DateUtil.getSystemDateTime("yyyy-MM-dd"));
		Message message = new Message();
		message.setTemplate("MT01601");
		message.setBaseKeyWord(keyWord);
		message.setSenderId(CommonDataUtil.getUserId());
		message.setReceiverEntId(approverEntId);
		messages.add(message);

		SmsAuthApplyKeyword authApplyKeyword = new SmsAuthApplyKeyword();
		authApplyKeyword.setAuthCompName(accreditationVo.getCustomerC().getCusName());
		authApplyKeyword.setApplyDate(DateUtil.getSystemDateTime("yyyy-MM-dd"));
		Message smsMessage = new Message();
		smsMessage.setTemplate("MT02618");
		smsMessage.setBaseKeyWord(authApplyKeyword);
		smsMessage.setSenderId(CommonDataUtil.getUserId());

		smsMessage.setReceiverEntId(approverEntId);
		messages.add(smsMessage);

		MsgEvent msgEvent = new MsgEvent();
		msgEvent.setMessages(messages);
		Observable<MsgEvent> msgObservers = Observable.just(msgEvent);
		msgObservers.subscribe(this.sendMsgSubscriber);
	}

	public List<UserVo> getOperators(String contactorId) {
		return this.accreditationDao.getOperators(contactorId);
	}

	public RetMsg firstTrialPass(CusOptVo cusOpt, BigDecimal crediLine) {
		CusRec cus = (CusRec) this.customerCService.selectByKey(cusOpt.getCusId());
		AccreditationVo accreditationVo = new AccreditationVo();
		accreditationVo.setCustomerC(cus);
		accreditationVo.setCreditLine(crediLine);
		cusOpt.setCusState("3");
		cusOpt.setNextState("E");
		cusOpt.setBizCode("1");

		AccreditEvent accreditEvent = new AccreditEvent();
		accreditEvent.setAccreditationVo(accreditationVo);
		accreditEvent.setCusOpt(cusOpt);

		Observable<AccreditEvent> observers = Observable.just(accreditEvent);
		observers.subscribe(this.setCusOptSubscriber);
		try {
			observers.subscribe(this.updateCusSubscriber);
		} catch (UnCheckMsgException e) {
			return new RetMsg("error", false, e.getMessage());
		}
		observers.subscribe(this.setCreditLineSubscriber);

		CusAcct cusAcct = this.pubCusAcctService.getPubCusAcct(cus.getCusId(), "N", "0");

		String approverEntId = this.cusGrpService.findGroupEnt(cus.getGrpId(), "GROUP_LAST_TRIAL");
		List<Message> messages = new ArrayList();

		Message message = new Message();
		SysAutLastTrialKeyword keyWord = new SysAutLastTrialKeyword();
		keyWord.setCusName(cus.getCusName());
		keyWord.setTrialName(CommonDataUtil.getCurUser().getUserName());
		keyWord.setApplyDate(SysDateUtil.parseDate(cusAcct.getCreateTime(), "yyyy-MM-dd HH:mm:ss", "yyyy-MM-dd"));
		message.setTemplate("MT01602");
		message.setBaseKeyWord(keyWord);
		message.setSenderId(CommonDataUtil.getUserId());
		message.setReceiverEntId(approverEntId);
		messages.add(message);

		MsgEvent msgEvent = new MsgEvent();
		msgEvent.setMessages(messages);
		Observable<MsgEvent> msgObservers = Observable.just(msgEvent);
		msgObservers.subscribe(this.sendMsgSubscriber);
		return new RetMsg("success", true, "������������");
	}

	public void firstTrialReject(CusOpt cusOpt) {
		CusRec cus = (CusRec) this.customerCService.selectByKey(cusOpt.getCusId());
		AccreditationVo accreditationVo = new AccreditationVo();
		accreditationVo.setCustomerC(cus);

		cusOpt.setCusState("5");
		cusOpt.setNextState("1");
		cusOpt.setBizCode("1");

		AccreditEvent accreditEvent = new AccreditEvent();
		accreditEvent.setAccreditationVo(accreditationVo);
		accreditEvent.setCusOpt(cusOpt);

		Observable<AccreditEvent> observers = Observable.just(accreditEvent);
		observers.subscribe(this.setCusOptSubscriber);
		observers.subscribe(this.updateCusSubscriber);

		List<Message> messages = new ArrayList();

		CusAcct pubCusAcct = this.pubCusAcctService.getPubCusAcct(cus.getCusId(), "N", "0");
		SmsAutRejectKeyword smsAutRejectKeyword = new SmsAutRejectKeyword();

		String accreditionDay = SysDateUtil.parseDate(pubCusAcct.getCreateTime(), "yyyy-MM-dd HH:mm:ss", "yyyy-MM-dd");
		smsAutRejectKeyword.setAccreditionDay(accreditionDay);

		smsAutRejectKeyword.setUrl(SpringContextUtil.getProperty("customer.website"));
		Message messageEnt = new Message();
		messageEnt.setTemplate("MT02105");
		messageEnt.setBaseKeyWord(smsAutRejectKeyword);
		messageEnt.setSenderId(CommonDataUtil.getUserId());
		messageEnt.setReceiverPhone(cus.getContactorPhone());
		messages.add(messageEnt);

		MsgEvent msgEvent = new MsgEvent();
		msgEvent.setMessages(messages);
		Observable<MsgEvent> msgObservers = Observable.just(msgEvent);
		msgObservers.subscribe(this.sendMsgSubscriber);
	}

	public RetMsg lastTrialPass(CusOptVo cusOpt) {
		CusRec cus = (CusRec) this.customerCService.selectByKey(cusOpt.getCusId());
		AccreditationVo accreditationVo = new AccreditationVo();
		accreditationVo.setCustomerC(cus);

		cusOpt.setCusState("E");
		cusOpt.setNextState("");
		cusOpt.setBizCode("2");

		AccreditEvent accreditEvent = new AccreditEvent();
		accreditEvent.setAccreditationVo(accreditationVo);
		accreditEvent.setCusOpt(cusOpt);

		accreditEvent.setNeedSync(true);

		Observable<AccreditEvent> observers = Observable.just(accreditEvent);
		observers.subscribe(this.setCusOptSubscriber);
		try {
			observers.subscribe(this.updateCusSubscriber);
		} catch (UnCheckMsgException e) {
			return new RetMsg("error", false, e.getMessage());
		}
		observers.subscribe(this.contSignSubscriber);
		observers.subscribe(this.setCusRelAndTagAfterAccreditSubscriber);
		observers.subscribe(this.setCusLvlSubscriber);
		observers.subscribe(this.cusAcctForPassSubscriber);
		observers.subscribe(this.updateUserAndOrganSubscriber);

		observers.subscribe(this.sendMsgForTbCusSubscriber);

		List<Message> messages = new ArrayList();

		List<PubUserVo> users = accreditEvent.getUserVos();
		SmsAutPassKeyword smsAutPassKeyword = new SmsAutPassKeyword();
		smsAutPassKeyword.setDays("7");
		smsAutPassKeyword.setNumber(String.valueOf(users.size()));
		smsAutPassKeyword.setUrl(SpringContextUtil.getProperty("customer.website"));
		Message message4 = new Message();
		if ("ENTERPRISE".equals(cus.getCusType())) {
			message4.setTemplate("MT02104");
		} else {
			message4.setTemplate("MT02110");
		}
		message4.setBaseKeyWord(smsAutPassKeyword);
		message4.setReceiverPhone(cus.getContactorPhone());
		messages.add(message4);

		UserVo admin = accreditationVo.getAdministrator();
		for (PubUserVo user : users) {
			if (!StringUtil.emptyAndNull(user.getUnencryptedPassword())) {
				SmsAutPwdKeyword smsAutPwdKeyword = new SmsAutPwdKeyword();

				smsAutPwdKeyword.setUrl(SpringContextUtil.getProperty("customer.website"));
				smsAutPwdKeyword.setLoginName(user.getLoginName());
				smsAutPwdKeyword.setCusName(admin.getUserName());
				smsAutPwdKeyword.setPassWord(user.getUnencryptedPassword());

				Message message3 = new Message();
				message3.setTemplate("MT02106");
				message3.setBaseKeyWord(smsAutPwdKeyword);
				message3.setReceiverPhone(user.getPhoneNo());
				messages.add(message3);
			}
		}
		MsgEvent msgEvent = new MsgEvent();
		msgEvent.setMessages(messages);
		Observable<MsgEvent> msgObservers = Observable.just(msgEvent);
		msgObservers.subscribe(this.sendMsgSubscriber);
		return new RetMsg("success", true, "������������");
	}

	public void lastTrialReject(CusOpt cusOpt) {
		CusRec cus = (CusRec) this.customerCService.selectByKey(cusOpt.getCusId());
		AccreditationVo accreditationVo = new AccreditationVo();
		accreditationVo.setCustomerC(cus);

		cusOpt.setCusState("4");
		cusOpt.setNextState("2");
		cusOpt.setCurState("3");
		cusOpt.setBizCode("2");

		AccreditEvent accreditEvent = new AccreditEvent();
		accreditEvent.setAccreditationVo(accreditationVo);
		accreditEvent.setCusOpt(cusOpt);

		Observable<AccreditEvent> observers = Observable.just(accreditEvent);
		observers.subscribe(this.setCusOptSubscriber);
		observers.subscribe(this.updateCusSubscriber);

		List<Message> messages = new ArrayList();

		SysAutRejectKeyword keyWord = new SysAutRejectKeyword();
		keyWord.setCusName(cus.getCusName());
		keyWord.setTrialName(CommonDataUtil.getCurUser().getUserName());
		CusOpt pubCusOpt = this.pubCusOptService.getLastOptByState(cus.getCusId(), "3", "1");
		Message message = new Message();
		message.setTemplate("MT01603");
		message.setBaseKeyWord(keyWord);
		message.setSenderId(CommonDataUtil.getUserId());
		message.setReceiverId(pubCusOpt.getOprId());
		messages.add(message);

		MsgEvent msgEvent = new MsgEvent();
		msgEvent.setMessages(messages);
		Observable<MsgEvent> msgObservers = Observable.just(msgEvent);
		msgObservers.subscribe(this.sendMsgSubscriber);
	}

	public void broadcastAfterAccredit(String cusId) {
		CusRec cus = (CusRec) this.customerCService.selectByKey(cusId);
		AccreditationVo accreditationVo = new AccreditationVo();
		accreditationVo.setCustomerC(cus);

		AccreditEvent accreditEvent = new AccreditEvent();
		accreditEvent.setAccreditationVo(accreditationVo);

		Observable<AccreditEvent> observers = Observable.just(accreditEvent);
		observers.subscribe(this.broadcastAfterAccreditSubscriber);
	}

	public Map<String, String> genAccreditationFiles(AccreditationVo accreditationVo) {
		Map<String, String> result = null;

		CusRec cusRec = accreditationVo.getCustomerC();
		UserVo userVo = accreditationVo.getAdministrator();

		String fileId = null;
		try {
			if ("on".equals(SpringContextUtil.getProperty("contract.switch"))) {
				Map<String, Object> params = new HashMap();
				result = new HashMap();
				Calendar calendar = Calendar.getInstance();
				params.put("cusName", cusRec.getCusName());
				params.put("loginName", userVo.getLoginName());
				params.put("year", Integer.valueOf(calendar.get(1)));
				params.put("month", Integer.valueOf(calendar.get(2) + 1));
				params.put("day", Integer.valueOf(calendar.get(5)));
				fileId = saveAccreditationFile(params, "7", "con_open_template");
				result.put("7", fileId);

				params.put("userName", userVo.getUserName());
				params.put("certNo", userVo.getCertNo());
				params.put("phoneNo", userVo.getPhoneNo());
				params.put("email", userVo.getEmail());
				fileId = saveAccreditationFile(params, "8", "con_auth_template");
				result.put("8", fileId);
			}
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}
		return result;
	}

	public String genCusAuthFile(AccreditationVo accreditationVo) {
		CusRec cusRec = accreditationVo.getCustomerC();
		if ((StringUtil.notEmpty(cusRec.getCusId())) && (StringUtil.empty(cusRec.getLrName()))) {
			cusRec = (CusRec) this.customerCService.selectByKey(cusRec.getCusId());
		}
		UserVo userVo = accreditationVo.getAdministrator();

		String fileId = null;
		try {
			AuthorizationKeyword keyword = getAuthorizationKeyword(cusRec, userVo);
			File pdf = genCusAuthFile(keyword);

			RetMsg retMsg = this.pubFileUploadService.saveFile(pdf, "9", "accreditation");
			if (pdf.exists()) {
				pdf.delete();
			}
			PubFile pubFile = (PubFile) retMsg.getBean();
			fileId = pubFile.getFileId();
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}
		return fileId;
	}

	private File genCusAuthFile(AuthorizationKeyword keyword) throws IOException {
		PubProtocol protocol = this.pubProtocolFeign.getPubProtocolByTypeAndGrpId("authorization_proto", "", "");
		String content = ContTemplateHelper.replaceContent(protocol.getContent(), keyword);

		String subDir = DateUtil.getSystemDate();
		String localPdfPath = ContConfiguration.getLocalPdfPath();
		if (StringUtil.emptyAndNull(localPdfPath)) {
			throw new UnCheckMsgException("������������������");
		}
		localPdfPath = localPdfPath + File.separator + subDir;

		File localDir = new File(localPdfPath);
		if (!localDir.exists()) {
			localDir.mkdir();
		}
		File pdf = PdfUtils.getPdfByContent(content, localPdfPath, protocol.getProtoName());
		return pdf;
	}

	private AuthorizationKeyword getAuthorizationKeyword(CusRec cusRec, UserVo userVo) {
		StringBuilder addressBuilder = new StringBuilder();
		if (!StringUtil.emptyAndNull(cusRec.getProvince())) {
			addressBuilder.append(cusRec.getProvince());
		}
		if (!StringUtil.emptyAndNull(cusRec.getCity())) {
			addressBuilder.append(cusRec.getCity());
		}
		addressBuilder.append(cusRec.getAddress());
		AuthorizationKeyword keyword = new AuthorizationKeyword();
		keyword.setCusName(cusRec.getCusName());
		keyword.setLrName(cusRec.getLrName());
		keyword.setAddress(addressBuilder.toString());
		keyword.setUserName(userVo.getUserName());
		keyword.setCertNo(userVo.getCertNo());
		keyword.setPhoneNo(userVo.getPhoneNo());
		return keyword;
	}

	public Result esignAccreditionFile(AccreditationVo accreditationVo) {
		AccreditEvent accreditEvent = new AccreditEvent();
		accreditEvent.setAccreditationVo(accreditationVo);

		Observable<AccreditEvent> observers = Observable.just(accreditEvent);

		observers.subscribe(this.esignOpenAcctSubscriber);
		observers.subscribe(this.contApplySubscriber);

		String acctId = accreditEvent.getStringValue("acctId");
		String mobile = accreditationVo.getAdministrator().getPhoneNo();
		Result result = this.esignSignService.getMobileCode(acctId, mobile);
		return result;
	}

	public SMSResponse cfcaAccreditionFile(AccreditationVo accreditationVo) {
		AccreditEvent accreditEvent = new AccreditEvent();
		accreditEvent.setAccreditationVo(accreditationVo);

		Observable<AccreditEvent> observers = Observable.just(accreditEvent);
		observers.subscribe(this.contApplySubscriber);

		PubUser user = accreditationVo.getAdministrator();
		String phoneCode = String.valueOf(RandomUtil.getRandomInt(6));
		PaperlessSignKeyWord keyword = new PaperlessSignKeyWord();
		keyword.setUserId(user.getUserId());
		keyword.setPhoneCode(phoneCode);
		keyword.setValidPeriod(String.valueOf(CfcaConfiguration.getCfcaSmsValidPeriod()));
		String keywordJson = null;
		try {
			keywordJson = JsonUtil.toJson(keyword);
		} catch (Exception e) {
			this.logger.error("json��������", e);
		}
		String keywordClassName = keyword.getClass().getName();
		SMSResponse response = this.pubMessageFeign.sendMessageToPhone(user.getPhoneNo(), "", "MT08011", keywordJson,
				keywordClassName);
		if (response.isSuccess()) {
			CfcaSmsLog cfcaSmsLog = new CfcaSmsLog();
			cfcaSmsLog.setSmsId(SystemUtil.getUUID());
			cfcaSmsLog.setPhoneNo(user.getPhoneNo());
			cfcaSmsLog.setPhoneCode(phoneCode);
			cfcaSmsLog.setUserId(user.getUserId());
			cfcaSmsLog.setSendTime(response.getSendTime());
			cfcaSmsLog.setSmsGateway(this.smsGateway);
			cfcaSmsLog.setContent(response.getContent());
			this.cfcaSmsLogService.save(cfcaSmsLog);
		}
		return response;
	}

	public RetMsg esignPayAmountAuth(BigDecimal amount) {
		String cusId = CommonDataUtil.getCurEntId();
		AccreditationVo accreditationVo = getCustomerInfo(cusId);
		CusAcct acct = accreditationVo.getCusAcct();
		RetMsg retMsg = this.esignAuthTxService.payAmountAuth(acct.getAcctNo(), amount);
		if (!"error".equals(retMsg.getType())) {
			CusOpt cusOpt = new CusOpt();
			cusOpt.setCusState("2");
			cusOpt.setNextState("3");
			cusOpt.setBizCode("0");
			cusOpt.setCurState(accreditationVo.getCustomerC().getCusState());

			AccreditEvent accreditEvent = new AccreditEvent();
			accreditEvent.setAccreditationVo(accreditationVo);
			accreditEvent.setCusOpt(cusOpt);

			Observable<AccreditEvent> observers = Observable.just(accreditEvent);

			observers.subscribe(this.setCusOptSubscriber);
			observers.subscribe(this.updateCusSubscriber);

			sendSaveAccreditationMsg(accreditEvent);
		}
		return retMsg;
	}

	public RetMsg payAmountVerification(BigDecimal amount) {
		String cusId = CommonDataUtil.getCurEntId();
		AccreditationVo accreditationVo = getCustomerInfo(cusId);
		CusAcct acct = accreditationVo.getCusAcct();
		RetMsg retMsg = new RetMsg();
		if (CustomerUtil.onEsign()) {
			retMsg = this.esignAuthTxService.payAmountAuth(acct.getAcctNo(), amount);
		}
		if (!"error".equals(retMsg.getType())) {
			CusOpt cusOpt = new CusOpt();
			cusOpt.setCusState("2");
			cusOpt.setNextState("3");
			cusOpt.setBizCode("0");
			cusOpt.setCurState(accreditationVo.getCustomerC().getCusState());

			AccreditEvent accreditEvent = new AccreditEvent();
			accreditEvent.setAccreditationVo(accreditationVo);
			accreditEvent.setCusOpt(cusOpt);

			Observable<AccreditEvent> observers = Observable.just(accreditEvent);

			observers.subscribe(this.setCusOptSubscriber);
			observers.subscribe(this.updateCusSubscriber);

			sendSaveAccreditationMsg(accreditEvent);
		}
		return retMsg;
	}

	public RetMsg saveCusAcct(CusAcct cusAcct) {
		String msg = "������������������";
		CusAcct ori = (CusAcct) this.pubCusAcctService.selectByKey(cusAcct.getAcctId());
		boolean updated = false;
		boolean updatedAcctNo = false;
		if (!ori.getAcctNo().equals(cusAcct.getAcctNo())) {
			updated = true;
			updatedAcctNo = true;
		}
		if (!ori.getAcctName().equals(cusAcct.getAcctName())) {
			updated = true;
		}
		if (!ori.getBankName().equals(cusAcct.getBankName())) {
			updated = true;
		}
		if (!ori.getBankDot().equals(cusAcct.getBankDot())) {
			updated = true;
		}
		if (!ori.getBankProvince().equals(cusAcct.getBankProvince())) {
			updated = true;
		}
		if (((StringUtil.emptyAndNull(ori.getBankCity())) && (!StringUtil.emptyAndNull(cusAcct.getBankCity())))
				|| ((StringUtil.notEmpty(ori.getBankCity())) && (!ori.getBankCity().equals(cusAcct.getBankCity())))) {
			updated = true;
		}
		if (updated) {
			try {
				String cusId = CommonDataUtil.getCurEntId();
				CusRec cus = (CusRec) this.customerCService.selectByKey(cusId);
				EsignAuthResponse response = this.esignAuthTxService.authBaseInfo(cus);
				if (response.getErrCode() != 0) {
					throw new UnCheckMsgException("������������������e������" + response.getMsg());
				}
				cusAcct.setCusId(cus.getCusId());
				EsignAuthResponse payResponse = this.esignAuthTxService.toPay(cusAcct, response.getServiceId());
				if (payResponse.getErrCode() != 0) {
					throw new UnCheckMsgException("������������������e������" + payResponse.getMsg());
				}
			} catch (Exception e) {
				return new RetMsg("error", true, e.getMessage());
			}
			this.pubCusAcctService.updateNotNull(cusAcct);
			if (updatedAcctNo) {
				this.cusAcctUseService.updateAcctNo(cusAcct.getAcctNo(), ori.getAcctNo(), "00");
			}
		}
		return new RetMsg("success", false, msg);
	}

	public CusAcct getCusAcct(String entId) {
		AccreditationVo vo = this.accreditationDao.getCustomerInfo(entId);
		return vo.getCusAcct();
	}

	public String esignAuthEntInfo(AccreditationVo accreditationVo) throws Exception {
		CusRec cus = accreditationVo.getCustomerC();

		CusAcct cusAcct = accreditationVo.getCusAcct();

		EsAcctAuth acctAuth = this.esignAuthTxService.getAcctAuth(cus.getCusId(), cusAcct.getAcctNo());
		if ((acctAuth == null) || ("2".equals(acctAuth.getAuthState()))) {
			EsignAuthResponse response = this.esignAuthTxService.authBaseInfo(cus);
			if (response.getErrCode() != 0) {
				return "������e������" + response.getMsg();
			}
			cusAcct.setCusId(cus.getCusId());
			EsignAuthResponse payResponse = this.esignAuthTxService.toPay(cusAcct, response.getServiceId());
			if (payResponse.getErrCode() != 0) {
				return "������e������" + payResponse.getMsg();
			}
		}
		return null;
	}

	public String cfcaAuthEntInfo(AccreditationVo accreditationVo) throws Exception {
		CusRec cusRec = accreditationVo.getCustomerC();

		CusAcct cusAcct = accreditationVo.getCusAcct();
		return this.cfcaAuthTxService.authEnt(cusRec, cusAcct, false);
	}

	public String cfcaAuthAdministrator(AccreditationVo accreditationVo, boolean isOperator) throws Exception {
		List<UserVo> list = new ArrayList();
		UserVo administrator;
		if (isOperator) {
			list = accreditationVo.getOperators();
		} else {
			administrator = accreditationVo.getAdministrator();
			list.add(administrator);
		}
		for (UserVo userVo : list) {
			if (!"platformUser".equals(userVo.getOperateType())) {
				String msg = this.cfcaAuthTxService.authUser(userVo);
				if (!StringUtil.emptyAndNull(msg)) {
					return msg;
				}
			}
		}
		return null;
	}

	public String esignAuthAdministrator(AccreditationVo accreditationVo) throws Exception {
		UserVo administrator = accreditationVo.getAdministrator();

		EsignAuthResponse response = this.esignAuthTxService.personTelecomAuth(administrator);
		if (response.getErrCode() != 0) {
			return "������e������" + response.getMsg();
		}
		return null;
	}

	public String esignAuthOperators(AccreditationVo accreditationVo) throws Exception {
		List<UserVo> operators = accreditationVo.getOperators();
		for (UserVo operator : operators) {
			if (!"platformUser".equals(operator.getOperateType())) {
				EsignAuthResponse response = this.esignAuthTxService.personTelecomAuth(operator);
				if (response.getErrCode() != 0) {
					return "������e������" + response.getMsg();
				}
			}
		}
		return null;
	}

	private String saveAccreditationFile(Map<String, Object> params, String fileType, String templateName)
			throws DocumentException, TemplateException, IOException {
		String templatePath = ACCREDITATION_TEMPLATE_PATH;
		if (SystemUtil.SystemMode.dev.equals(SystemUtil.getSystemMode())) {
			templatePath = templatePath.substring(templatePath.indexOf("/"));
		}
		File pdf = PdfUtils.convert2Pdf(templatePath, templateName, params, templatePath,
				(String) templateMap.get(templateName));
		RetMsg retMsg = this.pubFileUploadService.saveFile(pdf, fileType, "accreditation");
		if (pdf.exists()) {
			pdf.delete();
		}
		PubFile pubFile = (PubFile) retMsg.getBean();
		return pubFile.getFileId();
	}
}